package com.cnh.o2o.util.wechat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.security.SecureRandom;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.cnh.o2o.dto.UserAccessToken;
import com.cnh.o2o.dto.WechatUser;
import com.cnh.o2o.entity.PersonInfo;
import com.cnh.o2o.util.wechat.menu.Menu;
import com.cnh.o2o.util.wechat.menu.NormalAccessToken;
import com.cnh.o2o.util.wechat.menu.ViewButton;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 微信工具类
 * 
 * @author 陈南海
 *
 */
public class WechatUtil {
	private static Logger log = LoggerFactory.getLogger(WechatUtil.class);
	// 测试号信息里的appId
	private static final String APPID = "wxcf039af0b0bbffb4";
	// 测试号信息里的appsecret
	private static final String APPSECRET = "de9d064640606f1490c1496a6ffacef7";
	private static final String FRONTEND_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxcf039af0b0bbffb4&redirect_uri=http://520nh.viphk.ngrok.org/o2o/wechatlogin/logincheck&role_type=1&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect";
	private static final String SHOPEND_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxcf039af0b0bbffb4&redirect_uri=http://520nh.viphk.ngrok.org/o2o/wechatlogin/logincheck&role_type=2&response_type=code&scope=snsapi_userinfo&state=2#wechat_redirect";
	private static final String CREATE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
	private static final String NORMAL_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
	
	public static UserAccessToken getUserAccessToken(String code) throws IOException {
		log.debug(APPID);
		log.debug(APPSECRET);

		// 根据传入的code，拼接出访问微信定义好的接口的url
		String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + APPID + "&secret=" + APPSECRET
				+ "&code=" + code + "&grant_type=authorization_code";
		// 向相应url发送请求获取token json字符串
		String tokenStr = httpsRequest(url, "GET", null);

		log.debug("userAccessToken : " + tokenStr);

		UserAccessToken token = new UserAccessToken();
		ObjectMapper objectMapper = new ObjectMapper();
		try {
			// 将json字符串转化为相应对象
			token = objectMapper.readValue(tokenStr, UserAccessToken.class);
			log.debug(tokenStr);
		} catch (Exception e) {
			log.error("获取用户accessToken失败 ： " + e.getMessage());
			e.printStackTrace();
			JSONObject jsonObject = JSONObject.parseObject(tokenStr);
			if(jsonObject.getString("errcode") != null) {
				
			}
		}
		if (token == null) {
			log.error("获取用户accessToken失败。");
			return null;
		}

		return token;
	}

	/**
	 * 发起https请求并获取结果
	 * 
	 * @param requestUrl
	 *            请求地址
	 * @param requestMethod
	 *            请求方式（GET/POST）
	 * @param outputStr
	 *            提交的数据
	 * @return json字符串
	 */
	public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
		StringBuilder buffer = new StringBuilder();
		try {
			// 创建SSLContext对象，并使用我们指定的信任管理器初始化
			TrustManager[] tm = { new MyX509TrustManager() };
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new SecureRandom());
			// 从上述SSLContext对象中得到SSLSocketFactory对象
			SSLSocketFactory ssf = sslContext.getSocketFactory();
			URL url = new URL(requestUrl);
			HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
			httpUrlConn.setSSLSocketFactory(ssf);

			httpUrlConn.setDoOutput(true);
			httpUrlConn.setDoInput(true);
			httpUrlConn.setUseCaches(false);
			// 设置请求方式
			httpUrlConn.setRequestMethod(requestMethod);

			if ("GET".equalsIgnoreCase(requestMethod)) {
				httpUrlConn.connect();
			}

			// 当有数据需要提交时
			if (null != outputStr) {
				OutputStream outputStream = httpUrlConn.getOutputStream();
				// 注意编码格式，防止中文乱码
				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.close();
			}
			// 将返回的输入流转换成字符串
			InputStream inputStream = httpUrlConn.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

			String str = null;
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}
			// 释放资源
			bufferedReader.close();
			inputStreamReader.close();
			inputStream.close();
			inputStream = null;
			httpUrlConn.disconnect();

			log.debug("https buffer : " + buffer.toString());

		} catch (ConnectException ce) {
			log.error("wechat server connection timed out.");
		} catch (Exception e) {
			log.error("https request error:{}", e);
		}
		return buffer.toString();
	}

	/**
	 * 获取WechatUser实体类
	 * 
	 * @param accessToken
	 * @param openId
	 * @return
	 */
	public static WechatUser getUserInfo(String accessToken, String openId) {
		// 根据传入的accessToken以及openId拼接出访问微信定义的端口并获取用户信息的url
		String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openId
				+ "&lang=zh_CN";

		// 访问该url获取用户信息json字符串
		String userStr = httpsRequest(url, "GET", null);
		log.debug("user info : " + userStr);
		WechatUser user = new WechatUser();
		ObjectMapper objectMapper = new ObjectMapper();
		try {
			// 将json字符串转换成相应对象
			user = objectMapper.readValue(userStr, WechatUser.class);
		} catch (Exception e) {
			log.error("获取用户信息失败：" + e.getMessage());
			e.printStackTrace();
		}
		if (user == null) {
			log.error("获取用户信息失败.");
			return null;
		}
		return user;
	}

	/**
	 * 将wechatUser里的信息转换成PersonInfo的信息并返回PersonInfo对象
	 * @param user
	 * @return
	 */
	public static PersonInfo getPersonInfoFromRequest(WechatUser user) {
			PersonInfo personInfo = new PersonInfo();
			personInfo.setName(user.getNickName());
			personInfo.setGender(user.getSex() + "");
			personInfo.setProfileImg(user.getHeadimgurl());
			personInfo.setEnableStatus(1);
			return personInfo;
	}
	
	/**
	 * 菜单创建
	 * @return
	 */
	public static Menu initMenu() {

		ViewButton viewBtn1 = new ViewButton();
		viewBtn1.setName("顾客入口");
		viewBtn1.setType("view");
		viewBtn1.setUrl(FRONTEND_URL);
		
		ViewButton viewBtn2 = new ViewButton();
		viewBtn2.setName("店家系统");
		viewBtn2.setType("view");
		viewBtn2.setUrl(SHOPEND_URL);
		
		Menu menu = new Menu();
		menu.setButton(new ViewButton[]{viewBtn1, viewBtn2});
		return menu;	
	}
	/**
	 * 创建菜单
	 * @param token
	 * @param menu
	 * @return
	 */
	public static int createMenu(String token, String menu) {
		int result = 0;
		String url = CREATE_MENU_URL.replace("ACCESS_TOKEN", token);
		//
		JSONObject jsonObject = doPostStr(url, menu);
		if(jsonObject != null) {
			result = jsonObject.getIntValue("errcode");
		}
		return result;
	}
	/**
	 * get请求
	 * @param url
	 * @return
	 */
	public static JSONObject doGetStr(String url) {
		CloseableHttpClient httpClient = HttpClients.createDefault();
		HttpGet httpGet = new HttpGet(url);
		JSONObject jsonObject = null;
		try {
			HttpResponse response = httpClient.execute(httpGet);
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				String result = EntityUtils.toString(entity, "UTF-8");
				jsonObject = JSONObject.parseObject(result);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return jsonObject;
	}
	/**
	 * post请求
	 * @param url
	 * @param outstr
	 * @return
	 */
	public static JSONObject doPostStr(String url, String outstr) {
		CloseableHttpClient httpClient = HttpClients.createDefault();
		HttpPost httpPost = new HttpPost(url);
		JSONObject jsonObject = null;
		try {
			httpPost.setEntity(new StringEntity(outstr, "UTF-8"));
			HttpResponse response = httpClient.execute(httpPost);
			String result = EntityUtils.toString(response.getEntity(), "UTF-8");
			jsonObject = JSONObject.parseObject(result);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return jsonObject;
	}
	/**
	 * 获取普通的access_token
	 * @return
	 */
	public static NormalAccessToken geNormalAccessToken() {
		NormalAccessToken token = new NormalAccessToken();
		String url = NORMAL_ACCESS_TOKEN_URL.replace("APPID", APPID).replace("APPSECRET", APPSECRET);
		JSONObject jsonObject = doGetStr(url);
		if (jsonObject != null) {
			token.setToken(jsonObject.getString("access_token"));
			token.setExpiresIn(jsonObject.getIntValue("expires_in"));
		}
		return token;
	}
}
